package com.example.cursor.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.cursor.constant.CacheConstants;
import com.example.cursor.entity.Product;
import com.example.cursor.entity.SeckillRecord;
import com.example.cursor.exception.BusinessException;
import com.example.cursor.mapper.ProductMapper;
import com.example.cursor.mapper.SeckillRecordMapper;
import com.example.cursor.service.SeckillService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private SeckillRecordMapper seckillRecordMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final String SECKILL_LOCK_PREFIX = "seckill:lock:";

    @Override
    public Product getProduct(Long productId) {
        String cacheKey = CacheConstants.PRODUCT_CACHE_PREFIX + productId;

        // 1. 先从缓存获取
        String productJson = stringRedisTemplate.opsForValue().get(cacheKey);
        if (productJson != null) {
            return JSON.parseObject(productJson, Product.class);
        }

        // 2. 缓存未命中，查询数据库
        Product product = getProductFromDb(productId);
        if (product != null) {
            // 3. 更新缓存
            updateProductCache(product);
        }

        return product;
    }

    @Override
    public Product getProductFromDb(Long productId) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("PRODUCT_NOT_FOUND", "商品不存在");
        }
        return product;
    }

    @Override
    public void updateProductCache(Product product) {
        if (product != null) {
            String cacheKey = CacheConstants.PRODUCT_CACHE_PREFIX + product.getId();
            stringRedisTemplate.opsForValue().set(
                    cacheKey,
                    JSON.toJSONString(product),
                    CacheConstants.PRODUCT_CACHE_TIMEOUT,
                    TimeUnit.MINUTES
            );
        }
    }

    @Override
    public void deleteProductCache(Long productId) {
        String cacheKey = CacheConstants.PRODUCT_CACHE_PREFIX + productId;
        stringRedisTemplate.delete(cacheKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SeckillRecord doSeckill(Long userId, Long productId) {
        // 1. 检查用户是否已经秒杀过该商品
        if (checkUserSeckilled(userId, productId)) {
            throw new BusinessException("ALREADY_SECKILLED", "您已经秒杀过该商品");
        }

        // 2. 获取分布式锁
        String lockKey = SECKILL_LOCK_PREFIX + productId;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 尝试获取锁，最多等待3秒，30秒后自动释放
            boolean isLocked = lock.tryLock(3, 30, TimeUnit.SECONDS);
            if (!isLocked) {
                throw new BusinessException("SYSTEM_BUSY", "系统繁忙，请稍后再试");
            }

            // 3. 查询商品（直接查数据库，避免缓存数据不准确）
            Product product = getProductFromDb(productId);

            // 4. 检查库存
            if (product.getStock() <= 0) {
                throw new BusinessException("STOCK_NOT_ENOUGH", "商品已售罄");
            }

            // 5. 扣减库存（使用数据库行锁）
            int result = productMapper.decreaseStock(productId);
            if (result == 0) {
                throw new BusinessException("STOCK_NOT_ENOUGH", "商品已售罄");
            }

            // 6. 创建秒杀记录
            SeckillRecord record = new SeckillRecord();
            record.setUserId(userId);
            record.setProductId(productId);
            record.setCreateTime(LocalDateTime.now());
            seckillRecordMapper.insert(record);

            // 7. 更新商品缓存
            product.setStock(product.getStock() - 1);
            updateProductCache(product);

            return record;

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new BusinessException("SYSTEM_ERROR", "系统异常");
        } finally {
            // 确保当前线程持有锁的情况下才释放
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    public boolean checkUserSeckilled(Long userId, Long productId) {
        LambdaQueryWrapper<SeckillRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SeckillRecord::getUserId, userId)
                .eq(SeckillRecord::getProductId, productId);
        return seckillRecordMapper.selectCount(queryWrapper) > 0;
    }
}